package prototype

import (
	"fmt"
	"strconv"
)

// Prototype 声明一个克隆自身的接口
type Prototype interface {
	// Clone 克隆自身的方法，返回一个从自身克隆出来的对象
	Clone() Prototype
	Test() string
}

// ConcretePrototype1 克隆的具体实现对象
type ConcretePrototype1 struct {
	name string
	id   int
}

// Clone 克隆方法，复制属性值
func (c *ConcretePrototype1) Clone() Prototype {
	return &ConcretePrototype1{
		name: c.name + " clone ",
		id:   c.id,
	}
}

func (c *ConcretePrototype1) Test() string {
	return c.name + strconv.Itoa(c.id) + " type 1"
}

// ConcretePrototype2 克隆的具体实现对象
type ConcretePrototype2 struct {
	area string
	no   int
}

// Clone 克隆方法，复制属性值
func (c *ConcretePrototype2) Clone() Prototype {
	return &ConcretePrototype2{
		area: c.area + " clone ",
		no:   c.no,
	}
}

func (c *ConcretePrototype2) Test() string {
	return strconv.Itoa(c.no) + c.area + " type 2"
}

// Client 使用原型的客户端
type Client struct {
	// 持有需要使用的原型接口对象
	prototype Prototype
}

// NewClient 构造方法，传入需要使用的原型接口对象
func NewClient(prototype Prototype) *Client {
	return &Client{
		prototype: prototype,
	}
}

// Operation 示意方法，执行某个功能操作
func (c *Client) Operation() {
	// 需要创建原型接口的对象
	newPrototype := c.prototype.Clone()
	fmt.Println(newPrototype.Test())

}
